package com.rainyun.rcmc.bukkit;

import com.rainyun.rc.command.CmdArgs;
import com.rainyun.rc.command.CmdPath;
import com.rainyun.rc.command.ConvertException;
import com.rainyun.rc.config.NodeConfig;
import com.rainyun.rc.ioc.BeanPostInit;
import com.rainyun.rc.util.RainStr;
import com.rainyun.rcmc.own.common.BeanRc;
import com.rainyun.rcmc.own.config.RcLang;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;

import java.util.ArrayList;
import java.util.List;

public abstract class BukCmdPath extends CmdPath<CommandSender> implements BeanPostInit {

	public abstract Plugin getPlugin();

	public abstract void sendMsg(CommandSender sd,String msg);

	public abstract void sendWithPrefix(CommandSender sd,String msg);

	@Override
	public void help(CommandSender sd, String arg) {
		List<String> msglist = new ArrayList<String>();

		String helppre = getAttr("help_prefix");
		if(helppre!=null)msglist.add(helppre);

		String help = this.hasAttr("help")?this.getAttr("help"):this.getParentAttr("help");
		//获取节点帮助信息,若无帮助信息,自动寻找父节点帮助信息
		if(help!=null)msglist.add(help);
		
		List<String> tlist = new ArrayList<String>();
		this.getSubPaths().forEach((name,path)->{
			if(isTabWhenNotok()||globalCheck(sd,new CmdArgs(),false))//检查判断(也可以按情况去掉)
			if(name.startsWith(arg)&&path.hasAttr("help")) {
				tlist.add(path.getAttr("help"));
			}
		});
		if(tlist.isEmpty())
		this.getSubPaths().forEach((name,path)->{
			if(path.hasAttr("help"))tlist.add(path.getAttr("help"));
		});
		msglist.addAll(tlist);

		String helpsuf = getAttr("help_suffix");
		if(helpsuf!=null)msglist.add(helpsuf);

		String msg = RainStr.join(msglist.toArray(new String[msglist.size()]),"\n");
		//结合为单字符串
		if(sd instanceof ConsoleCommandSender)
			msg="\n"+msg;//对于后台,加个换行保证美观

		sendMsg(sd,msg);//发送信息
	}

	@BeanRc(BeanRc.BeansRc.NodeConf)
	static NodeConfig<?> ncf;

	@Override
	public boolean globalCheck(CommandSender sd, CmdArgs ca, boolean ready) {
		//检查方法
		String msg = null;//错误信息
		
		if(this.checkAttr("console",true)&&sd instanceof Player) {
			msg = ncf.get(RcLang.cmd_console);
		}else if(this.checkAttr("ingame",true)&&sd instanceof ConsoleCommandSender) {
			msg = ncf.get(RcLang.cmd_ingame);
		}else {
			String perm = this.getAttr("perm");
			if(perm!=null&&!sd.hasPermission(perm)){
				msg = ncf.get(RcLang.cmd_perm).
						toString().replace("{perm}",perm);
			}
		}
		if(msg!=null&&ready) {//执行前发送错误信息
			sendWithPrefix(sd,msg);
		}
		return msg==null;
		//假如提示错误信息为null,就代表检查通过
	}

	@Override
	public <T> T convert(Class<T> clazz,String str,CommandSender sd) throws ConvertException{
		try {
			T result = super.convert(clazz,str,sd);
			if(result==null) {
				if(clazz.equals(Player.class)) {
					Player p = Bukkit.getPlayer(str);
					if(p==null) {
						sendWithPrefix(sd, ncf.get(RcLang.biz_notonline)
								.toString().replace("{player}",str));
						throw new ConvertException(Player.class);
					}
					result=(T) p;
				}else if(clazz.equals(OfflinePlayer.class)) {
					OfflinePlayer p = Bukkit.getOfflinePlayer(str);
					if(p==null) {
						sendWithPrefix(sd, ncf.get(RcLang.biz_noplayer)
								.toString().replace("{player}",str));
						throw new ConvertException(OfflinePlayer.class);
					}
					result=(T) p;
				}
			}
			return result;
		} catch (ConvertException e) {
			Class<?> type = e.getConvertClass();
			if(type.getSuperclass()!=null)
			if(type.getSuperclass().equals(Number.class)) {
				if(type.equals(Double.class)||type.equals(Float.class)) {
					sendWithPrefix(sd, ncf.get(RcLang.cmd_double)
							.toString().replace("{value}",str));
				}else {
					sendWithPrefix(sd, ncf.get(RcLang.cmd_int)
							.toString().replace("{value}",str));
				}
			}else {
				sendWithPrefix(sd, ncf.get(RcLang.cmd_boolean)
						.toString().replace("{value}",str));
			}
			throw e;
		}
	}

	@Override
	public void excute(CommandSender sd, CmdArgs ca,boolean async) {
		BukkitScheduler sche = Bukkit.getScheduler();
		if(async)
			sche.runTaskAsynchronously(getPlugin(),()->{
				try {
					getComExec().excute(sd,ca);
				}catch (Throwable e){
					handleExecError(sd,e);
				}
			});
		else
			sche.runTask(getPlugin(),()->{
				try {
					getComExec().excute(sd,ca);
				}catch (Throwable e){
					handleExecError(sd,e);
				}
			});
	}
}


